package org.test4j.mock;

/**
 * mock method proxy
 * 可以作为mock方法的第一个参数
 *
 * @author darui.wu
 */
public abstract class Invocation {
    /**
     * 执行方法原有的逻辑
     * <p>
     * Allows execution to proceed into the real implementation of the target method/constructor.
     *
     * @param args 传递给方法的参数(可以是原始入参, 也可以是mock逻辑中篡改过的参数)
     * @param <T>  the return type of the target method
     * @return
     */
    public abstract <T> T proceed(Object... args);

    /**
     * 执行方法mock前的逻辑, 入参是原始入参
     *
     * @param <T>
     * @return
     */
    public <T> T proceed() {
        return this.proceed(this.getArgs());
    }

    /**
     * 当前执行实例(即相当于Java内置的变量this), 静态方法返回null
     * <p>
     * Returns the instance on which the current invocation was made
     */
    public abstract <T> T getTarget();

    /**
     * 获得方法的入参列表
     *
     * @return
     */
    public abstract Object[] getArgs();

    /**
     * 获得第index个参数, index从0开始
     *
     * @param index
     * @return
     */
    public <ARG> ARG arg(int index) {
        return (ARG) this.getArgs()[index];
    }

    /**
     * 获得第index个参数, index从0开始; 并强制转换为类型ARG
     *
     * @param index
     * @param clazz 强转类型
     * @return
     */
    public <ARG> ARG arg(int index, Class<ARG> clazz) {
        return (ARG) this.getArgs()[index];
    }

    /**
     * 返回方法是被第几次调用
     *
     * @return
     */
    public abstract int getInvokedTimes();
}